use std::collections::HashMap;
use std::time::{SystemTime, UNIX_EPOCH};
use serde::{Deserialize, Serialize};

/// 节点状态枚举（运行/可用性语义）
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum NodeStatus {
    /// Node status is unknown
    Unknown,
    /// Node is healthy and responding
    Healthy,
    /// Node is experiencing issues but still reachable
    Degraded,
    /// Node is not responding
    Offline,
    /// Node has been removed from the cluster
    Removed,
    /// Node is active and running
    Active,
    /// Node is inactive but available
    Inactive,
    /// Node is down
    Down,
    /// Node is in maintenance mode
    Maintenance,
}

impl NodeStatus {
    /// 是否被视为活跃（Healthy / Degraded / Active）
    pub fn is_active(&self) -> bool {
        matches!(self, NodeStatus::Healthy | NodeStatus::Degraded | NodeStatus::Active)
    }

    /// 是否可用于业务操作（同 is_active，未来可拆分）
    pub fn is_available(&self) -> bool {
        matches!(self, NodeStatus::Healthy | NodeStatus::Degraded | NodeStatus::Active)
    }
}

/// 可提交到集群的操作类型（用于客户端 -> 状态机）
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum Operation {
    /// Add a new node to the cluster
    AddNode {
        id: String,
        address: String,
        metadata: HashMap<String, String>,
    },
    /// Remove a node from the cluster
    RemoveNode { id: String },
    /// Update node metadata
    UpdateNode {
        id: String,
        address: Option<String>,
        metadata: Option<HashMap<String, String>>,
    },
    /// Update cluster configuration
    UpdateConfig {
        key: String,
        value: serde_json::Value,
    },
    /// Custom application-specific operation
    Custom { data: serde_json::Value },
}

/// 发送到集群的请求（封装操作 + 元信息）
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Request {
    /// The operation to perform
    pub operation: Operation,
    /// Optional client ID for tracing
    pub client_id: Option<String>,
    /// Timestamp when the request was created (as seconds since Unix epoch)
    pub timestamp: u64,
}

impl Request {
    /// 创建新请求（无 client_id）
    pub fn new(operation: Operation) -> Self {
        Self {
            operation,
            client_id: None,
            timestamp: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap_or_default()
                .as_secs(),
        }
    }

    /// 创建带 client_id 的请求（便于追踪溯源）
    pub fn with_client_id(operation: Operation, client_id: String) -> Self {
        Self {
            operation,
            client_id: Some(client_id),
            timestamp: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap_or_default()
                .as_secs(),
        }
    }
}

/// 集群返回的响应
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Response {
    /// The result of the operation
    pub result: OperationResult,
    /// The node ID that processed the request
    pub node_id: String,
    /// Timestamp when the response was created (as seconds since Unix epoch)
    pub timestamp: u64,
}

impl Response {
    /// 构造成功响应
    pub fn success(node_id: String) -> Self {
        Self {
            result: OperationResult::Success,
            node_id,
            timestamp: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap_or_default()
                .as_secs(),
        }
    }

    /// 构造错误响应
    pub fn error(node_id: String, message: String) -> Self {
        Self {
            result: OperationResult::Error { message },
            node_id,
            timestamp: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap_or_default()
                .as_secs(),
        }
    }
}

/// Result of an operation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum OperationResult {
    /// Operation completed successfully
    Success,
    /// Operation failed with an error message
    Error { message: String },
    /// Operation returned data
    Data { value: serde_json::Value },
}

/// 节点元信息（存储于状态机）
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct NodeInfo {
    /// Unique identifier for the node
    pub id: String,
    /// Network address of the node
    pub address: String,
    /// Current status of the node
    pub status: NodeStatus,
    /// Arbitrary metadata associated with the node
    pub metadata: HashMap<String, String>,
    /// When the node was last seen (as seconds since Unix epoch)
    pub last_seen: u64,
    /// When the node joined the cluster (as seconds since Unix epoch)
    pub joined_at: u64,
}

impl NodeInfo {
    /// 创建新节点（默认状态 Active，时间戳为当前）
    pub fn new(id: String, address: String) -> Self {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap_or_default()
            .as_secs();

        Self {
            id,
            address,
            status: NodeStatus::Active,
            metadata: HashMap::new(),
            last_seen: now,
            joined_at: now,
        }
    }

    /// 基于上次心跳时间判断是否视为离线
    pub fn is_offline(&self, timeout_secs: u64) -> bool {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap_or_default()
            .as_secs();
        now.saturating_sub(self.last_seen) > timeout_secs
    }

    /// 更新 last_seen 时间戳为当前
    pub fn update_last_seen(&mut self) {
        self.last_seen = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap_or_default()
            .as_secs();
    }
}

/// Metrics related to cluster operations
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClusterMetrics {
    /// Total number of nodes
    pub total_nodes: usize,
    /// Number of healthy nodes
    pub healthy_nodes: usize,
    /// Number of operations performed
    pub total_operations: u64,
    /// Number of failed operations
    pub failed_operations: u64,
    /// Average response time in milliseconds
    pub avg_response_time_ms: f64,
}

impl Default for ClusterMetrics {
    fn default() -> Self {
        Self {
            total_nodes: 0,
            healthy_nodes: 0,
            total_operations: 0,
            failed_operations: 0,
            avg_response_time_ms: 0.0,
        }
    }
}

/// 健康检查结果（简化版，与 cluster/health 模块区分）
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthCheckResult {
    /// Name of the health check
    pub name: String,
    /// Whether the check passed
    pub passed: bool,
    /// Optional message with details
    pub message: Option<String>,
    /// Duration of the check in milliseconds
    pub duration_ms: u64,
}

/// 节点整体健康状态（汇总）
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthStatus {
    /// Node ID
    pub node_id: String,
    /// Overall status
    pub status: NodeStatus,
    /// Individual health check results
    pub checks: Vec<HealthCheckResult>,
    /// Timestamp of the health check (as seconds since Unix epoch)
    pub timestamp: u64,
}

impl HealthStatus {
    /// 构造新的健康状态对象
    pub fn new(node_id: String, status: NodeStatus, checks: Vec<HealthCheckResult>) -> Self {
        Self {
            node_id,
            status,
            checks,
            timestamp: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap_or_default()
                .as_secs(),
        }
    }
}

/// Node metrics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NodeMetrics {
    /// Node ID
    pub node_id: String,
    /// CPU usage percentage (0-100)
    pub cpu_usage: f64,
    /// Memory usage percentage (0-100)
    pub memory_usage: f64,
    /// Network I/O in bytes per second
    pub network_io_bps: u64,
    /// Response time in milliseconds
    pub response_time_ms: f64,
    /// Timestamp when metrics were collected (as seconds since Unix epoch)
    pub timestamp: u64,
}

impl NodeMetrics {
    /// 创建新的节点指标对象（初始值为 0）
    pub fn new(node_id: String) -> Self {
        Self {
            node_id,
            cpu_usage: 0.0,
            memory_usage: 0.0,
            network_io_bps: 0,
            response_time_ms: 0.0,
            timestamp: SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap_or_default()
                .as_secs(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_request_creation() {
        let operation = Operation::AddNode {
            id: "test-node".to_string(),
            address: "127.0.0.1:8080".to_string(),
            metadata: HashMap::new(),
        };

        let request = Request::new(operation.clone());
        assert_eq!(request.operation, operation);
        assert!(request.client_id.is_none());
        assert!(request.timestamp > 0);
    }

    #[test]
    fn test_node_info_creation() {
        let node = NodeInfo::new("test-node".to_string(), "127.0.0.1:8080".to_string());
        assert_eq!(node.id, "test-node");
        assert_eq!(node.address, "127.0.0.1:8080");
        assert_eq!(node.status, NodeStatus::Active);
        assert!(node.last_seen > 0);
        assert!(node.joined_at > 0);
    }

    #[test]
    fn test_node_status_is_active() {
        assert!(NodeStatus::Active.is_active());
        assert!(NodeStatus::Healthy.is_active());
        assert!(NodeStatus::Degraded.is_active());
        assert!(!NodeStatus::Offline.is_active());
        assert!(!NodeStatus::Down.is_active());
    }
}
